namespace Vanilla.UI

import System

// BOX
class Box (Gadget):
	public DrawFrame = true	
	
	public PassMouseEventsToChildren = true
	
	// CHILDREN
	public Children as (Gadget)
	
	virtual def Add (child as Gadget):
		return if child in Children or child == null
		
		unless child.Parent is null:
			child.Parent.Remove(child)
		
		if Children == null:
			Children = (child,)
		else:
			Children = Children + (child,)
		
		PauseDrawing()
		PausePacking()
		Parent.Pack() unless Parent == null
		Pack()
		ResumePacking()
		ResumeDrawing()
		
		old = child.Parent
		child.Parent = self
		
		child.Reparented(old, self)
	
	virtual def Remove (child as Gadget):
		return if Children == null or not child in Children
		
		child.Parent = null
		ch as (Gadget) = array(Gadget,0)
		for i in Children:
			ch += (i,) if i != child
		Children = ch
		Pack()
	
	virtual def RemoveAll ():
		return if Children == null
		
		for i in Children:
			Remove(i)
	
	// PACK
	virtual def Pack ():
		return if Children == null
		super()
	
	// DRAW CONTENTS
	virtual def DrawContents (b as Brush):
		return if Children == null
		for g as Gadget in Children:
			if b.ClipArea.Overlaps(g.Rect):
				b.Save()
				
				b.Draw(g.Rect)
				b.Clip()
				b.Translate(g.Rect.X, g.Rect.Y)
				g.Draw(b)
				
				b.Restore()
	
	// CONTAINS / CHILDAT
	def ChildAt (x as double, y as double) as Gadget:
		return if Children == null
		for c as Gadget in reversed(Children):
			return c if c.Contains(x-c.Rect.X, y-c.Rect.Y)
	
	def ChildAtMousePosition (x as double, y as double) as Gadget:
		return if Children == null
		for c as Gadget in reversed(Children):
			return c if c.ContainsMouseAt(x-c.Rect.X, y-c.Rect.Y)
	
	override def Contains (x as double, y as double) as bool:
		return Size.Contains(x,y)
		//if DrawFrame:
		//	return super(x,y)
		//else:
		//	return super(x,y) and ChildAt(x,y) != null
	
	override def ContainsMouseAt(x as double, y as double) as bool:
		return Size.Contains(x,y) //return super(x,y) and ChildAtMousePosition(x,y) != null
	
	override def Contains (g as Gadget) as bool:
		return false if Children == null or g == null
		for c in Children:
			return true if c == g or c.Contains(g)
	
	// MOUSE EVENTS
	override def MouseMotion (x as double, y as double):
		super(x,y)
	
		return if Children == null or BeingDragged
	
		if Contains(GadgetWithMouseGrabbed):
			for c in Children:
				if c.ContainsMouseGrabber:
					c.MouseMotion(x - c.Rect.X, y - c.Rect.Y)
					return
	
		return unless PassMouseEventsToChildren
		
		new_childat as bool = PreviousGadgetUnderMouse == null
		PreviousGadgetUnderMouse = GadgetUnderMouse if new_childat
		
		c = ChildAtMousePosition(x,y)
		if c != null:
			//print "${GetType()}.ChildAt(${x},${y}) --> ${c.GetType()}"
			
			//print "prev=${PreviousGadgetUnderMouse}"
			GadgetUnderMouse = c
			//print "under=${GadgetUnderMouse}"
			
			for i in Children:
				i.MouseLeave() if i.PreviouslyContainedMouse and not i.ContainsMouse
			
			if GadgetUnderMouse != null:
				unless GadgetUnderMouse.PreviouslyContainedMouse:
					GadgetUnderMouse.MouseEnter()
				GadgetUnderMouse.MouseMotion(x-GadgetUnderMouse.Rect.X, y-GadgetUnderMouse.Rect.Y)
			
		else:
			for i in Children:
				i.MouseLeave() if i.PreviouslyContainedMouse
				
		PreviousGadgetUnderMouse = null if new_childat
	
	override def Drop (g as Gadget, x as double, y as double):
		print "${GetType} droptatoes"
		c = ChildAtMousePosition(x,y)
		
		if c != null and c.AcceptsDrop(g,x,y):
			c.Drop(g, x - c.Rect.X, y - c.Rect.Y)
		else:
			Add(g)
			GadgetBeingDragged = null
	
	override def AcceptsDrop (g as Gadget, x as double, y as double) as bool:
		return true if AcceptsDrops
		return false unless PassMouseEventsToChildren
		c = ChildAtMousePosition(x,y)
		return false if c is null
		return c.AcceptsDrop(g, x - c.Rect.X, y - c.Rect.Y)
	
	override def MouseLeave ():
		return if Children == null
	
		new_childat as bool = PreviousGadgetUnderMouse == null
		
//		if new_childat:
		PreviousGadgetUnderMouse = GadgetUnderMouse if new_childat
		
		for c in Children:
			c.MouseLeave() if c.PreviouslyContainedMouse
		super()
		
		PreviousGadgetUnderMouse = null if new_childat
	
	override def MouseDown (b as MouseButton, x as double, y as double):
		super(b,x,y)
		
		if Contains(GadgetWithMouseGrabbed):
			for c in Children:
				if c.ContainsMouseGrabber:
					c.MouseDown(b, x - c.Rect.X, y - c.Rect.Y)
					return
		
		return unless PassMouseEventsToChildren
		
		c = ChildAtMousePosition(x,y)
		if c != null:
			c.MouseDown(b, x-c.Rect.X, y-c.Rect.Y)
			
	override def MouseUp (b as MouseButton, x as double, y as double):
		super(b,x,y)
		
		if Contains(GadgetWithMouseGrabbed):
			for c in Children:
				if c.ContainsMouseGrabber:
					c.MouseUp(b, x - c.Rect.X, y - c.Rect.Y)
					return
		
		return unless PassMouseEventsToChildren
		
		c = ChildAtMousePosition(x,y)
		if c != null:
			print "${GetType()}.ChildAtMousePosition(${x}, ${y}) -> ${c.GetType()}"
			c.MouseUp(b, x-c.Rect.X, y-c.Rect.Y)
		else:
			print "${GetType()}.ChildAtMousePosition(${x}, ${y}) -> null"
	
	// SPACING
	_spacing as double = double.NaN
	virtual Spacing as double:
		get:
			if double.IsNaN(_spacing):
				return Theme.DefaultSpacingFor(self)
			else:
				return _spacing
		set:
			_spacing = value
	
	// ROUNDING (yeah no idea where i'm going with this... makes the calculator look nicer though)
	rounding as int = 10
	virtual Rounding as int:
		get:
			return rounding
		set:
			rounding = value
	
	// CONSTRUCTOR
	def constructor (p as Box):
		Children = (,) as (Gadget)
		super(p)
	
	def constructor (p as Box, f as bool):
		self(p)
		DrawFrame = f
	
	// TOSTRING
	/* -- clogs up debug info
	def ToString ():
		start = "<" + GetType().ToString() + " rect=\"" + Rect.ToString() + "\">"
		if Children != null:
			for c in Children:
				start += c.ToString()
		return start + "</" + GetType().ToString() + ">"
	*/
	
	// KEYBOARD EVENTS
	override def KeyDown (c as char, k as Key):
		super(c,k)
		
		return if Children == null
		
		for i in Children:
			if i.IsFocused:
				i.KeyDown(c,k)
	
	override def KeyUp (c as char, k as Key):
		super(c,k)
		
		return if Children == null
		
		for i in Children:
			if i.IsFocused:
				i.KeyUp(c,k)
